# -*- coding: utf-8 -*-
#
# 认证,和自定request的中间件
#

import datetime
import time
import json
import logging
import traceback

from django.views import debug
from django.db import connection
from django.http import HttpResponse
from django.shortcuts import render_to_response, HttpResponseRedirect
from django.core.cache import cache

from package.models.admin import Admin
# from analysis.models.log import Log
from center.settings import DEBUG  # , CACHES, STATIC_ROOT

_log = logging.getLogger('root')


def get_real_ip(request):
    """
    获取真实ip
    """
    return request.META.get('HTTP_REMOTE_ADDR2', '') or request.META.get(
        'HTTP_X_FORWARDED_FOR', '') or request.META.get('REMOTE_ADDR')


def list_transform(dic, ignore=None):
    """
    request.GET接收内容list转换
    """
    for k, v in dic.items():
        if not ignore or k not in ignore:
            dic[k] = v[-1]
    return dic


class CustomRequestMiddleware(object):
    """
    自定义request处理,增加一些方法和属性
    """

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        self.process_request(request)
        response = self.get_response(request)
        return response

    def process_request(self, request):
        request.POST._mutable = True
        request.GET._mutable = True
        request.real_ip = get_real_ip(request)
        request.is_debug = DEBUG
        request.get_dic = list_transform(dict(request.GET))
        request.post_dic = list_transform(dict(request.POST))
        request._start_time = time.time()

    def process_view(self, request, view_func, view_args, view_kwargs):
        pass

    def process_response(self, request, response):
        return response

    def process_exception(self, request, exception):
        """
        出错处理
        """
        pass
        # return debug.technical_500_response(request, *sys.exc_info())  这个处理会导致不打印报错

    def print_sql(self):
        """
        打印sql
        """
        print('-' * 20, 'sql:', '-' * 20)
        for i, d in enumerate(connection.queries):
            print('<%s> %s : %s' % (i + 1, d['time'], d['sql']))


class AuthMiddleware(object):
    """
    认证的中间件
    """

    def __init__(self, get_response):
        """
         用于第一次启动项目加载全部缓存
        """
        # if 'open' in CACHES and CACHES['open']:
        #     try:
        #         cache_role_keys = cache.get('cache_role_key', set())
        #         if not cache_role_keys:
        #             load_all_cache()
        #     except Exception as e:
        #         msg = '第一次启动项目加载全部缓存%s' % e
        #         print(msg)
        # else:
        #     pass
        # create_initial_json()
        self.get_response = get_response

    def __call__(self, request):
        request_query_dict = request.GET.copy()
        request_query_dict.update(request.POST.copy())
        request.REQUEST = request_query_dict
        response = self.get_response(request)
        return response

    def process_request(self, request):
        pass

    def process_view(self, request, view_func, view_args, view_kwargs):
        """
        静态文件及有"notauth" 属性view_func 免认证
        """
        if hasattr(view_func, 'notauth') or view_func.__module__ == 'django.views.static':  # 不需处理的函数不管
            is_allow = True
            if request.path_info.find('/login') == 0 and request.method == 'POST':
                request.admin = Admin()
                request.admin.id = 0
                # self.save_operate_log(request, '登录后台')
        else:
            admin_id = request.session.get('admin_id', None)
            the_admin = Admin.get_admin(admin_id)
            request.admin = the_admin
            if not request.admin:
                return HttpResponseRedirect('/login?from_url=%s' % request.get_full_path())

            admin_menus = request.admin.resource.menu.using('read')
            _admin_menu_map = {}
            for m in admin_menus.all():
                menu_name = m.name
                _admin_menu_map[menu_name] = m
            request.allow_menu = _admin_menu_map
            is_allow = self.check_url_permission(request)
            # if 'open' in CACHES and CACHES['open']:
            #     self.set_server_cache(request)
            # else:
            roles = request.admin.get_roles()
            role_ids_key = '_'.join(sorted([str(role.id) for role in roles]))
            request.role_ids_key = role_ids_key
        if not is_allow:
            if request.is_ajax():
                return HttpResponse('{"code":1,"content":[],"msg":"没有权限!"}')
            return render_to_response('block.html', locals())

    def process_response(self, request, response):
        return response

    def process_exception(self, request, exception):
        pass

    def check_url_permission(self, request):
        """
        检查请求URL的权限
        """
        is_allow = False
        match_menu = None
        url_path = request.path_info
        params = dict(request.REQUEST)
        # 管理员的菜单里查询匹配项目
        for k, menu in request.allow_menu.items():
            if url_path == menu.url_path and menu.is_match_url_parmas(params):
                match_menu = menu
                is_allow = True
                break

        if match_menu:
            if match_menu.is_log:
                pass
                # self.save_operate_log(request, match_menu.name)
        if request.admin.is_root:  # 管理员直接过
            is_allow = True
        return is_allow

    def save_operate_log(self, request, msg, log_type=29):
        """
        写入用户操作记录
        """
        try:
            Log._meta.db_table = 'log_operate'
            log = Log()
            log.log_type = log_type
            log.log_server = 0
            log.log_channel = 0
            log.log_user = request.admin.id
            log.log_data = 0
            log.log_result = 0
            log.f1 = msg[:100]
            log.f2 = request.get_full_path()[:100]
            log.f3 = request.real_ip
            post_params = str(json.dumps(dict(request.POST), ensure_ascii=False))
            log.f4 = post_params[:100]
            log.f5 = post_params[100:200]
            log.f6 = post_params[300:400]
            log.log_time = datetime.datetime.now()
            log.save(using='write')
        except Exception as e:
            traceback.print_exc()
            # create_table_sql = Log.get_create_table_sql('log_operate')
            conn = connection
            cur = conn.cursor()
            cur.execute(create_table_sql)
            print(e)

    # def set_server_cache(self, request):
    #     try:
    #         roles = request.admin.get_roles()
    #         role_ids_key = '_'.join(sorted([str(role.id) for role in roles]))
    #         request.role_ids_key = role_ids_key  # 用作区分角色缓存的key
    #         # 将缓存设置到request对象中
    #         is_expire = False
    #         for pre_cache_key in CACHE_KEY:  # 判断服务器页面缓存是否过期
    #             cache_key = pre_cache_key + request.role_ids_key
    #             cache_page = cache.get(cache_key)
    #             if cache_page:
    #                 request.__setattr__(pre_cache_key, cache_key)
    #             else:
    #                 break
    #         else:
    #             is_expire = True  # 无页面过期
    #
    #         if not is_expire:  # 有页面过期更新缓存
    #             load_role_cache(roles)  # 要同步加载完缓存才能往下给request设置缓存
    #             for pre_cache_key in CACHE_KEY:
    #                 cache_key = pre_cache_key + request.role_ids_key
    #                 request.__setattr__(pre_cache_key, cache_key)

        except Exception as e:
            msg = '中间件缓存:%s' % e
            _log.error(msg)
            print(msg)


# def create_initial_json():
#     """
#     初始化json文件
#     :return:
#     """
#     initial_json_dict = {
#         'server': [('activity.json',{}), ('all_server.json',{}), ('login_notice.json',{}), ('url.json',{}),
#                    ('chat_limit.json',{}), ('chat_notice.json',{}),
#                    ('bad_word.json',[]), ('ip_white.json',{}), ('ip_white_list.json',[]), ('notice.json',{}),
#                    ('operation_activity.json',[]), ('username_white.json',{}), ('all_game_notice.json',{}),
#                    ('roll_notice.json',[]),('real_name_value.json',{}),('real_name_auth.json',{})],
#         'client': []}
#     for name, json_list in initial_json_dict.items():
#         base_json_path = os.path.abspath(os.path.join(STATIC_ROOT, name))
#         if not os.path.exists(base_json_path):
#             os.makedirs(base_json_path)
#         for json_dict in json_list:
#             path = os.path.join(base_json_path, json_dict[0])
#             if not os.path.exists(path):
#                 with open(path, 'w', encoding='utf8') as f:
#                     f.write(json.dumps(json_dict[1]))
